#ifndef __MYLIB_H_
#define __MYLIB_H_

/*************Configure**************/

#define HAVE_STDIO_H 1
#define HAVE_PTHREAD_H 1
#define HAVE_DELAY_US_H 1
#define HAVE_WRITEN_READN_H 1
#define HAVE_READLINE_H 1
#define HAVE_SOCKET_H 1
#define HAVE_FIFO_H 1
#define HAVE_CRC_H 1
#define HAVE_QUEUE_H 1

#if HAVE_QUEUE_H
#undef HAVE_PTHREAD_H
#define HAVE_PTHREAD_H 1
#endif

//unix
#define HAVE_MQUEUE_H 0   	//posix
#define HAVE_SEMAPHORE_H 1
#define HAVE_SYS_MMAN_H 0

#define HAVE_SYS_IPC_H 1	//system v
#define HAVE_SYS_MSG_H 1
#define HAVE_SYS_SEM_H 1
#define HAVE_SYS_SHM_H 1



#define HAVE_SYS_SIGNAL_H 1
#define HAVE_SYS_SELECT_H 1
#define HAVE_SYS_SYSCTL_H 1
#define HAVE_POLL_H 1
#define HAVE_STROPTS_H 1
#define HAVE_SYS_IOCTL_H 1
#define HAVE_SYS_FILIO_H 1

#define HAVE_POLL 1
#define HAVE_FATTACH 1
#define HAVE_VSNPRINTF 1
#define HAVE_SIGINFO_T_STRUCT 1
#define HAVE_SIGWAIT 1
#define HAVE_VALLOC 1
#define HAVE_STRINGS_H 1
#define HAVE_HASHLIST_H 1

/*************Configure end**************/

#include	<sys/types.h>	/* basic system data types */
#include	<sys/time.h>		/* timeval{} for select() */
#include	<time.h>			/* timespec{} for pselect() */
#include	<errno.h>
#include	<fcntl.h>			/* for nonblocking */
#include	<limits.h>		/* PIPE_BUF */
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<sys/stat.h>		/* for S_xxx file mode constants */
#include	<unistd.h>
#include	<sys/wait.h>

#if HAVE_SOCKET_H
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif 

#if HAVE_SYS_SIGNAL_H
#include	<signal.h>
#endif

#if	HAVE_MQUEUE_H
#include	<mqueue.h>		/* Posix message queues */
#endif

#if	HAVE_SEMAPHORE_H
#include	<semaphore.h>	/* Posix semaphores */
#ifndef	SEM_FAILED
#define	SEM_FAILED	((sem_t *)(-1))
#endif
#endif

#if	HAVE_SYS_MMAN_H
#include	<sys/mman.h>	/* Posix shared memory */
#endif

#if	HAVE_PTHREAD_H
#include	<pthread.h>
#endif

#ifndef	MAP_FAILED
#define	MAP_FAILED	((void *)(-1))
#endif

#ifdef	__bsdi__
#define	va_mode_t	int
#else
#define	va_mode_t	mode_t
#endif

#if	HAVE_SYS_IPC_H
#include	<sys/ipc.h>		/* System V IPC */
#endif

#if	HAVE_SYS_MSG_H
#include	<sys/msg.h>		/* System V message queues */
#endif

#if	HAVE_SYS_SEM_H
#include	<sys/sem.h>		/* System V semaphores */
#ifndef	HAVE_SEMUN_UNION
union semun {				/* define union for semctl() */
  int              val;
  struct semid_ds *buf;
  unsigned short  *array;
};
#endif
#endif						/* HAVE_SYS_SEM_H */

#if	HAVE_SYS_SHM_H
#include	<sys/shm.h>		/* System V shared memory */
#endif



#if	HAVE_SYS_SELECT_H
#include	<sys/select.h>	/* for convenience */
#endif

#if	HAVE_POLL_H
#include	<poll.h>		/* for convenience */
#endif

#if	HAVE_STROPTS_H
#include	<stropts.h>		/* for convenience */
#endif

#if	HAVE_STRINGS_H
#include	<strings.h>		/* for convenience */
#endif

#if	HAVE_SYS_IOCTL_H
#include	<sys/ioctl.h>
#endif

/*
#if	HAVE_SYS_FILIO_H
# include	<sys/filio.h>
#endif
*/


#ifndef min
#define	min(a,b)		((a) < (b) ? (a) : (b))
#endif

#ifndef max
#define	max(a,b)	((a) > (b) ? (a) : (b))
#endif

#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a)		(sizeof((a)) / sizeof((a)[0]))	
#endif

//error.c
void	 err_dump(const char *, ...);
void	 err_msg(const char *, ...);
void	 err_quit(const char *, ...);
void	 err_ret(const char *, ...);
void	 err_sys(const char *, ...);

//wrapsock.c
#if HAVE_SOCKET_H
int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr);
void Bind(int fd, const struct sockaddr *sa, socklen_t salen);
void Connect(int fd, const struct sockaddr *sa, socklen_t salen);
void Getpeername(int fd, struct sockaddr *sa, socklen_t *salenptr);
void Getsockname(int fd, struct sockaddr *sa, socklen_t *salenptr);
void Getsockopt(int fd, int level, int optname, void *optval, socklen_t *optlenptr);
int Isfdtype(int fd, int fdtype);
void Listen(int fd, int backlog);
ssize_t Recv(int fd, void *ptr, size_t nbytes, int flags);
ssize_t Recvfrom(int fd, void *ptr, size_t nbytes, int flags, struct sockaddr *sa, socklen_t *salenptr);
ssize_t Recvmsg(int fd, struct msghdr *msg, int flags);
void Send(int fd, const void *ptr, size_t nbytes, int flags);
void Sendto(int fd, const void *ptr, size_t nbytes, int flags, const struct sockaddr *sa, socklen_t salen);
void Sendmsg(int fd, const struct msghdr *msg, int flags);
void Setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen);
void Shutdown(int fd, int how);
int Sockatmark(int fd);
int Socket(int family, int type, int protocol);
void Socketpair(int family, int type, int protocol, int *fd);
const char *Inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
void Inet_pton(int family, const char *strptr, void *addrptr);
#endif

//wrapstdio.h
#if HAVE_STDIO_H
void	 Fclose(FILE *);
FILE	*Fdopen(int, const char *);
char	*Fgets(char *, int, FILE *);
FILE	*Fopen(const char *, const char *);
void	 Fputs(const char *, FILE *);
FILE	*Popen(const char *, const char *);
int Pclose(FILE *);
#endif

//wrappthread.c
#if HAVE_PTHREAD_H
void	 Pthread_attr_init(pthread_attr_t *);
void	 Pthread_attr_destroy(pthread_attr_t *);
void	 Pthread_attr_setdetachstate(pthread_attr_t *, int);
void	 Pthread_attr_setscope(pthread_attr_t *, int);
void	 Pthread_create(pthread_t *, const pthread_attr_t *, void * (*)(void *), void *);
void	 Pthread_join(pthread_t, void **);
void	 Pthread_detach(pthread_t);
void	 Pthread_kill(pthread_t, int);
void	 Pthread_setcancelstate(int, int *);
void	 Pthread_mutexattr_init(pthread_mutexattr_t *);
void	 Pthread_mutexattr_destroy(pthread_mutexattr_t *);
void	 Pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
void	 Pthread_mutex_init(pthread_mutex_t *, pthread_mutexattr_t *);
void  Pthread_cond_init(pthread_cond_t *, pthread_condattr_t *);
void	 Pthread_mutex_destroy(pthread_mutex_t *);
void	 Pthread_mutex_lock(pthread_mutex_t *);
void	 Pthread_mutex_unlock(pthread_mutex_t *);
void	 Pthread_condattr_init(pthread_condattr_t *);
void	 Pthread_condattr_destroy(pthread_condattr_t *);
void	 Pthread_condattr_setpshared(pthread_condattr_t *, int);
void	 Pthread_cond_broadcast(pthread_cond_t *);
void	 Pthread_cond_signal(pthread_cond_t *);
void	 Pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
int	 Pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
void	 Pthread_key_create(pthread_key_t *, void (*)(void *));
void	 Pthread_setspecific(pthread_key_t, const void *);
void	 Pthread_once(pthread_once_t *, void (*)(void));
long	 pr_thread_id(pthread_t *);
void Pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
void Pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
void Pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
void Pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
void Pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

#endif

//sleep_us.c
#if HAVE_DELAY_US_H
void Sleep_us(unsigned int nusecs);
#endif

#if HAVE_WRITEN_READN_H
ssize_t Readn(int fd, void *ptr, size_t nbytes);
void Writen(int fd, void *ptr, size_t nbytes);
#endif

#if HAVE_READLINE_H
ssize_t Readline(int fd, void *ptr, size_t maxlen);
#endif

//wrapunix.c
void	*Calloc(size_t, size_t);
void	 Close(int);
void	 Dup2(int, int);
int Fcntl(int, int, void *);
pid_t Fork(void);
long	 Fpathconf(int, int);
void	 Fstat(int, struct stat *);
key_t Ftok(const char *, int);
void	 Ftruncate(int, off_t);
int Getopt(int, char *const *, const char *);
void	 Gettimeofday(struct timeval *, void *);
int Ioctl(int, int, void *);
void	 Kill(pid_t, int);
off_t	 Lseek(int, off_t, int);
void	*Malloc(size_t);
void	 Mkfifo(const char *, mode_t);
void	 Mktemp(char *);

#if HAVE_SYS_MMAN_H
void	*Mmap(void *, size_t, int, int, int, off_t);
void	 Munmap(void *, size_t);
#endif

int Open(const char *, int, ...);
long	 Pathconf(const char *, int);
void	 Pipe(int *fds);
ssize_t Read(int, void *, size_t);
int Select(int, fd_set *, fd_set *, fd_set *, struct timeval *);

#if HAVE_SYS_SIGNAL_H
typedef	void	Sigfunc(int);	/* for signal handlers */
Sigfunc *Signal(int signo, Sigfunc *func);
void	 Sigaddset(sigset_t *, int);
void	 Sigdelset(sigset_t *, int);
void	 Sigemptyset(sigset_t *);
void	 Sigfillset(sigset_t *);
int Sigismember(const sigset_t *, int);
void	 Sigpending(sigset_t *);
void	 Sigprocmask(int, const sigset_t *, sigset_t *);
#if	HAVE_SIGINFO_T_STRUCT
void	 Sigqueue(pid_t, int, const union sigval);
#endif
#if	HAVE_SIGWAIT
void	 Sigwait(const sigset_t *, int *);
#endif
#endif

void	 Stat(const char *, struct stat *);
char	*Strdup(const char *);
long	 Sysconf(int);

#if	HAVE_SYS_SYSCTL_H
void	 Sysctl(int *, u_int, void *, size_t *, void *, size_t);
#endif

void	 Unlink(const char *);
void	*Valloc(size_t);
pid_t Wait(int *);
pid_t Waitpid(pid_t, int *, int);
void	 Write(int, void *, size_t);

#if	HAVE_MQUEUE_H
mqd_t Mq_open(const char *, int, ...);
void	 Mq_close(mqd_t);
void	 Mq_unlink(const char *pathname);
void	 Mq_send(mqd_t, const char *, size_t, unsigned int);
ssize_t Mq_receive(mqd_t, char *, size_t, unsigned int *);
void	 Mq_notify(mqd_t, const struct sigevent *);
void	 Mq_getattr(mqd_t, struct mq_attr *);
void	 Mq_setattr(mqd_t, const struct mq_attr *, struct mq_attr *);
#endif	/* HAVE_MQUEUE_H */

#if	HAVE_SEMAPHORE_H
sem_t *Sem_open(const char *, int, ...);
void	 Sem_close(sem_t *);
void	 Sem_unlink(const char *);
void	 Sem_init(sem_t *, int, unsigned int);
void	 Sem_destroy(sem_t *);
void	 Sem_wait(sem_t *);
int		 Sem_trywait(sem_t *);
void	 Sem_post(sem_t *);
void	 Sem_getvalue(sem_t *, int *);
#endif	/* HAVE_SEMAPHORE_H */

#if	HAVE_SYS_MMAN_H
int Shm_open(const char *, int, mode_t);
void Shm_unlink(const char *);
#endif

#if	HAVE_SYS_MSG_H
int Msgget(key_t key, int flag);
void	 Msgctl(int, int, struct msqid_ds *);
void	 Msgsnd(int, const void *, size_t, int);
ssize_t Msgrcv(int, void *, size_t, int, int);
#endif	/* HAVE_SYS_MSG_H */

#if	HAVE_SYS_SEM_H
int Semget(key_t, int, int);
int Semctl(int, int, int, ...);
void	 Semop(int, struct sembuf *, size_t);
#endif	/* HAVE_SYS_SEM_H */

#if	HAVE_SYS_SHM_H
int Shmget(key_t, size_t, int);
void	*Shmat(int, const void *, int);
void	 Shmdt(const void *);
void	 Shmctl(int, int, struct shmid_ds *);
#endif	/* HAVE_SYS_SHM_H */

#if HAVE_FIFO_H
struct fifo 
{
	unsigned char *buffer;	/* the buffer holding the data */
	unsigned int size;	/* the size of the allocated buffer */
	unsigned int in;	/* data is added at offset (in % size) */
	unsigned int out;	/* data is extracted from off. (out % size) */
};

struct fifo *fifo_init(unsigned int size);
void fifo_destroy(struct fifo *self);
unsigned int fifo_write(struct fifo *self, const void *from, unsigned int len);
unsigned int fifo_read(struct fifo *self, void *to, unsigned int len);

#endif

#if HAVE_QUEUE_H
typedef struct
{
	char queue_name[20];
	pthread_cond_t cond;
	pthread_mutex_t mutex;
	unsigned int ctr;
	unsigned int inPtr;
	unsigned int outPtr;
	unsigned int size;
	void	**bufptr;
} S_QUEUE, *PS_QUEUE;

PS_QUEUE QueueInit(const char *pcName, size_t size);
void *QueueGet(PS_QUEUE psQueue);
void *QueueGetTime(PS_QUEUE psQueue, int s);
void QueuePut(PS_QUEUE psQueue, void *ptr);
void QueueDel(PS_QUEUE psQueue);
#endif

#if HAVE_CRC_H
unsigned short CalCRC(char *ptr, size_t len);
#endif

int Asc2Hex(unsigned char *hexa, int hexlen, char *str, int len);
int Hex2Asc(char *str, int len, unsigned char *hexa, int hexlen);
void Asc2Int(unsigned int *dest, const char *str, int len);
void Otc2Int(unsigned int *dest, const char *str, int len);

#if HAVE_HASHLIST_H 

typedef unsigned long (* hash_count_cp)(void *);
typedef int (* hash_compare_cp)(void *, void *);
typedef void *(* hash_copy_key_cp)(void *);
typedef void *(* hash_copy_value_cp)(void *);
typedef void (* hash_free_key_cp)(void *);
typedef void (*hash_free_value_cp)(void *);

struct hash_list_entry
{
	void *key;						//the key of stored element 
	void *value;						//content of stored element
	//struct hash_list_entry *pstNext;		//the next entry head
	//struct hash_list_entry *pstPrev;		//previous entry head 
	struct hash_list_entry *pstList;		//next entry list
};

struct hash_list_operation
{
	hash_count_cp fun_count;
	hash_compare_cp fun_compare;
	hash_copy_key_cp fun_copy_key;
	hash_copy_value_cp fun_copy_value;
	//hash_free_key_cp fun_free_key;
	//hash_free_value_cp fun_free_value;
};

struct hash_list
{
	struct hash_list_entry **ppstHash_table; 	//table of hash_list entries
	unsigned int table_size;					//size of hash_list head
	unsigned int element_size;					//size of hash_list items
	unsigned int mode;						//mode of the object
	pthread_rwlock_t lock;						//rw lock
	hash_count_cp fun_count;
	hash_compare_cp fun_compare;
	hash_copy_key_cp fun_copy_key;
	hash_copy_value_cp fun_copy_value;
	//struct hash_list_operation *pstOp;			//the operation of hash object
};

//struct hash_list *hash_create(unsigned int mode, unsigned int size, struct hash_list_operation *pstAttr);
struct hash_list *hash_create(unsigned int mode, 
							unsigned int size, 
							hash_count_cp count_cp,
							hash_compare_cp compare_cp,
							hash_copy_key_cp copy_key_cp,
							hash_copy_value_cp copy_value_cp);
void *hash_search_list(struct hash_list *self, void *key);
struct hash_list_entry *hash_insert_list(struct hash_list *self, void *key, void *value);
int hash_del_entry(struct hash_list *self, void *key);
int hash_destroy(struct hash_list *self);
#endif


#endif
